home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////////////////////////////////////
- //
- // Hyphen.c
- // --------
- // Skeleton MPW Hyphen tool
- //
- //////////////////////////////////////////////////////////////////
-
- #pragma load "managers"
-
- //////////////////////////////////////////////////////////////////
- //
- // Constants and Macros
- //
- //////////////////////////////////////////////////////////////////
-
- #define nil 0
-
- #define stdinfd 0
- #define stdoutfd 1
- #define stderrfd 2
-
- #define stdunit(x) ((x >= stdinfd) && (x <= stderrfd))
- #define notstdunit(x) (x > stderrfd)
-
- #define nombuffsize 1024
- #define truebuffsize 1200
-
- //////////////////////////////////////////////////////////////////
- //
- // Types
- //
- //////////////////////////////////////////////////////////////////
-
- typedef enum {false, true} logical;
- typedef enum {nocode, pascalcode, ccode} codetype;
-
- //////////////////////////////////////////////////////////////////
- //
- // Globals
- //
- //////////////////////////////////////////////////////////////////
-
- //////////////////////////////////////////////////////////////////
- //
- // Prototypes
- //
- //////////////////////////////////////////////////////////////////
-
- void initmac();
- int openoutput(char *thename, int output);
- int readinput(int input, Handle inbuffer, int buffersize);
- int filter(char *inbuffer, int buffersize, int output, codetype language);
- int writeoutput(int output, char *outbuffer, int buffersize);
-
- //////////////////////////////////////////////////////////////////
- //
- // main
- // ----
- // the "main" routine reads and interprets the command line,
- // concatenates input files into an input buffer, opens the
- // output file, and calls the "filter" routine to write the
- // output.
- //
- //////////////////////////////////////////////////////////////////
-
- int main(int argc, char *argv[])
- {
-
- int index;
- int input;
- int output;
- codetype language;
- Handle inbuffer;
- int buffersize;
- char *thetail;
-
- initmac();
-
- // "input" is the fd of the input file, initially stdin
- // "output" is the fd of the output file, initially stdout
- // "language" is the language to parse, initially unknown
-
- input = stdinfd;
- output = stdoutfd;
- language = nocode;
-
- // "inbuffer" is the input buffer,
- // initially empty but able to grow
- // "buffersize" is the size of "inbuffer"
-
- inbuffer = NewHandle(0);
- buffersize = 0;
-
- // command line interpreter: loop through command options
-
- for (index = 1; index < argc; index++)
- {
-
- if (argv[index][0] == '-')
- {
-
- switch (argv[index][1])
- {
-
- // "-p" and "-c" options set language type;
- // these override any previous setting
-
- case 'P':
- case 'p':
- language = pascalcode;
- break;
-
- case 'C':
- case 'c':
- language = ccode;
- break;
-
- case 'O':
- case 'o':
- output = openoutput(argv[++index], output);
- if (output < 0)
- {
- fprintf(stderr, "Error - Unable to open "
- "output file %s!\n", argv[index]);
- exit(2);
- }
- break;
-
- default:
- fprintf(stderr, "Error - Unknown option %s\n", argv[index]);
- exit(2);
- break;
-
- }
-
- }
- else
- {
-
- // if "language" has not changed since initialization,
- // set "language" according to file name (the
- // first input file thus determines language type)
-
- if (language == nocode)
- {
- thetail = argv[index] + strlen(argv[index]) - 2;
- if (strcmp(thetail, ".p") == 0)
- language = pascalcode;
- else if (strcmp(thetail, ".c") == 0)
- language = ccode;
- }
-
- // open the input file (after this step, "input"
- // will NOT contain a standard unit number)
- // and read it into the input buffer
-
- input = open(argv[index], O_RDONLY);
- if (input < 0)
- {
- fprintf(stderr, "Error - Unable to open "
- "input file %s!\n", argv[index]);
- exit(2);
- }
-
- buffersize = readinput(input, inbuffer, buffersize);
- if (buffersize < 0)
- {
- fprintf(stderr, "Error - Reading from %s!\n", argv[index]);
- exit(2);
- }
-
- close(input);
-
- }
-
- }
-
- // if "input" is still a standard unit number, then no
- // input file was opened, and input must be from
- // standard input
-
- if (stdunit(input))
- {
- buffersize = readinput(input, inbuffer, buffersize);
- if (buffersize < 0)
- {
- fprintf(stderr, "Error - Reading from standard input!\n");
- exit(2);
- }
- }
-
- // if "language" is still unknown, set it to Pascal
-
- if (language == nocode)
- language = pascalcode;
-
- // the routine "filter" does the real work of the program
-
- HLock(inbuffer);
- filter(*inbuffer, buffersize, output, language);
- HUnlock(inbuffer);
-
- // wrapup: close "output" first if the program opened it
-
- DisposHandle(inbuffer);
-
- if (notstdunit(output))
- close(output);
-
- exit(0);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // initmac
- // -------
- // initialize any necessary managers and whatnot.
- //
- //////////////////////////////////////////////////////////////////
-
- void initmac()
- {
-
- InitGraf((Ptr)&qd.thePort);
- SetFScaleDisable(true);
-
- InitCursorCtl(nil);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // openoutput
- // ----------
- // open the output file. returns the fd or, if an error
- // occurs, the error flag.
- //
- //////////////////////////////////////////////////////////////////
-
- int openoutput(char *thename, int output)
- {
-
- FInfo theinfo;
-
- // if "output" is not a standard unit, then an output
- // file must have already be open
-
- if (notstdunit(output))
- {
- fprintf(stderr, "Warning - additional output "
- "file %s ignored!\n", thename);
- return(output);
- }
-
- // open the output file for writing (O_WRONLY),
- // creating it if necessary (O_CREAT) and
- // zeroing it otherwise (O_TRUNC)
-
- output = open(thename, O_WRONLY + O_CREAT + O_TRUNC);
- if (output < 0)
- return(output);
-
- // if the file was created by "open", it will be
- // untyped, so set the type to TEXT and MPS
-
- if (getfinfo(thename, 0, &theinfo))
- {
- fprintf(stderr, "Warning - unable to get info for "
- "output file %s!\n", thename);
- return(output);
- }
-
- theinfo.fdType = 'TEXT';
- theinfo.fdCreator = 'MPS ';
-
- if (setfinfo(thename, 0, &theinfo))
- fprintf(stderr, "Warning - unable to set info for "
- "output file %s!\n", thename);
-
- return(output);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // readinput
- // ---------
- // this routine appends an input file to the input buffer and
- // returns the new size of the buffer or, if a read error
- // occurs, the error flag.
- //
- //////////////////////////////////////////////////////////////////
-
- int readinput(int input, Handle inbuffer, int buffersize)
- {
-
- int readsize;
-
- SetHandleSize(inbuffer, buffersize + 1024);
- HLock(inbuffer);
-
- while ((readsize = read(input, *inbuffer + buffersize, 1024)) > 0)
- {
- buffersize += readsize;
- HUnlock(inbuffer);
- SetHandleSize(inbuffer, buffersize + 1024);
- HLock(inbuffer);
- }
-
- if (readsize < 0)
- return(readsize);
-
- HUnlock(inbuffer);
- SetHandleSize(inbuffer, buffersize + 1024);
-
- return(buffersize);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // filter
- // ------
- // this routine does the main work of the program.
- //
- //////////////////////////////////////////////////////////////////
-
- int filter(char *inbuffer, int buffersize, int output, codetype language)
- {
-
- int inposition;
- int outposition;
- Handle thehandle;
- char *classtable;
- char *statetable;
- char outbuffer[truebuffsize];
- int thestate;
- unsigned char thechar;
- int theclass;
- int newstate;
- int writesize;
-
- // "inposition" keeps track of the current position in the
- // input buffer, initially at the beginning
- // "outposition" keeps track of the current position in the
- // output buffer, initially at the beginning
-
- inposition = 0;
- outposition = 0;
-
- // "classtable" is the character classification table,
- // and "statetable" is set according to language
- // type; note that both will be disposed of by
- // CloseResFile on exit, since they're resources
-
- thehandle = GetResource('TABL', 1000);
- HLock(thehandle);
- classtable = *thehandle;
-
- if (language == pascalcode)
- thehandle = GetResource('TABL', 1001);
- else
- thehandle = GetResource('TABL', 1002);
- HLock(thehandle);
- statetable = *thehandle;
-
- // start the machine in state 0
-
- thestate = 0;
- while (inposition < buffersize)
- {
-
- // fetch a character from the input buffer
-
- thechar = *(inbuffer + inposition++);
-
- // determine the new state
-
- theclass = classtable[thechar];
- newstate = statetable[12 * thestate + theclass];
-
- // overwrite an embedded hyphen
-
- if ((thestate == 6) && (newstate == 5))
- outposition--;
-
- // copy input to the output buffer
-
- outbuffer[outposition++] = thechar;
-
- // back up if necessary
-
- if (newstate == 0)
- {
-
- switch (thestate)
- {
-
- case 2:
- case 5:
- inposition--;
- outposition--;
- break;
-
- case 6:
- inposition -= 2;
- outposition -= 2;
- break;
-
- }
-
- }
-
- // when the output buffer fills up, write it to output
-
- if ((outposition >= nombuffsize) && ((thestate != 5) || (newstate != 6)))
- {
- outposition = writeoutput(output, outbuffer, outposition);
- if (outposition < 0)
- return(outposition);
- }
-
- // shift to the new state
-
- thestate = newstate;
-
- }
-
- // write whatever is left in the buffer directly to output
-
- writesize = write(output, outbuffer, outposition);
- return(writesize);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // writeoutput
- // ----------
- // this routine flushes the output buffer by writing
- // it to the output file. It returns the new size of the
- // buffer or, if a write error occurs, the error flag.
- //
- //////////////////////////////////////////////////////////////////
-
- int writeoutput(int output, char *outbuffer, int buffersize)
- {
-
- int writesize;
-
- writesize = write(output, outbuffer, nombuffsize);
-
- if (writesize < 0)
- return(writesize);
-
- buffersize -= writesize;
- BlockMove(outbuffer + writesize, outbuffer, buffersize);
-
- return(buffersize);
-
- }
-
- //////////////////////////////////////////////////////////////////
-